/**
 * @fileoverview Creates and control chart appearance.
 */

/**
 * Column type in the DataTable.  This assumes a single data series in the
 * table.
 *
 * VALUE  = actual value of the data cell.
 * SELECT = selected value.
 *
 * See clear / setSelection for more details.
 */
var Column = {
  CATEGORY: 0,
  VALUE: 1,
  ANNOTATION_VALUE: 2,
  SELECT: 3,
  ANNOTATION_SELECT: 4
}

/**
 * Addition options customized for each story.
 */
var ChartOptions = {
  0: {hAxis: 'Percentage of GDP'},
  1: {hAxis: 'Number of immigrants as a percentage of population'},
  2: {hAxis: 'Number of countries per sport'},
  3: {hAxis: 'Millions USD'}
}

/**
 * Options sent to the google.visualization.BarChart. The final option is the
 * union of Options and ChartOptions.
 */
var Options = {
  width: 500,
  height: 400,
  chartArea: {top: 0, height: 350, left: 105},
  legend: 'none',
  isStacked: true,
  tooltip: {trigger: 'both'}
}

var DATA_RANDOM_SEQUENCE = [
    31, 22, 17, 2, 16, 11, 19, 27, 7, 25,
    10, 5, 4, 1, 23, 14, 6, 13, 18, 26,
    15, 8, 20, 29, 21, 28, 3, 24, 9, 12, 30];

/**
 * Creates the google.visualizaiton.BarChart.
 * @return {Element} the container of the chart.
 */
function createChart(opt_showAnnotations, opt_lastSelectedRow) {
  data = google.visualization.arrayToDataTable(
      randomizeDataOrder(stories[storyIndex].data));
  data.addColumn({type: 'string', role: 'tooltip'});

  // Adds a special column to 'highlight' rows.  See clear / setSelection for
  // details.
  data.addColumn('number', 'select');
  data.addColumn({type: 'string', role: 'tooltip'});

  // Controls the content of the tooltips.
  fixTooltips();

  var container = document.createElement('div');
  container.id = 'chart-container';
  stage.appendChild(container);
  chart = new google.visualization.BarChart(container);

  google.visualization.events.addListener(chart, 'select', onChartSelect);
  google.visualization.events.addListener(chart, 'onmouseover', onChartHover);

  // Adds special annotations for the GRAPHIC condition.
  annotations = opt_showAnnotations ?
      stories[storyIndex].annotations : null;
  google.visualization.events.addListener(chart, 'ready', onChartReady);

  // Saves the last selected row to replicate the chart.
  lastSelectedRow = opt_lastSelectedRow;

  return container;
}

/**
 * @parma {Array.<Array.<string, number>>}
 * @return {Array.<Array.<string.number>>}
 */
function randomizeDataOrder(data) {
  var randomData = [data[0]];
  for (var i = 0; i < DATA_RANDOM_SEQUENCE.length; i++) {
    var seq = DATA_RANDOM_SEQUENCE[i];
    if (seq < data.length) {
      randomData.push(data[seq]);
    }
  }
  return randomData;
}

/**
 * Draws the chart.
 */
function drawChart() {
  Options.hAxis = {title: ChartOptions[storyIndex].hAxis};
  chart.draw(data, Options);
}

/**
 * Adds the tool tip values to both the original and select columns.
 */
function fixTooltips() {
  for (var i = 0; i < data.getNumberOfRows(); i++) {
    var tooltipContent = data.getValue(i, Column.CATEGORY) + ':' +
        data.getValue(i, Column.VALUE)
    data.setValue(i, Column.ANNOTATION_VALUE, tooltipContent);
    data.setValue(i, Column.ANNOTATION_SELECT, tooltipContent);
  }
}

/**
 * Saves the selected row.
 */
function onChartSelect() {
  if (chart.getSelection()[0]) {
    lastSelectedRow = chart.getSelection()[0].row;
    logChartEvent('select', data.getValue(lastSelectedRow, Column.CATEGORY));
  }
}

/**
 * Save the hover row and let the selection persists.
 */
function onChartHover(evt) {
  lastSelectedRow = evt.row;
  chart.setSelection([{row: lastSelectedRow, column: Column.VALUE}]);
  logChartEvent('mouseover', data.getValue(lastSelectedRow, Column.CATEGORY)); 
}

/**
 * Can only add stuff on the chart once the chart is completely rendered.
 * This is to avoid problems in FireFox.
 */
function onChartReady(evt) {
  var container = document.getElementById('chart-container');
  addAnnotations(container, annotations);
  if (lastSelectedRow) {
    chart.setSelection([{row: lastSelectedRow, column: Column.VALUE}]);
  }  
  google.visualization.events.removeListener(onChartReady);
}

/**
 * Adds annotations on top of the charts.
 * @param {Element} container To which to add the annotations.
 * @param {Array.<{{string, string}>} annotations Category of the row (to
 *    identify the row) and text to be added.
 */
function addAnnotations(container, annotations) {
  if (!annotations) {
    return;
  }

  // Needs this to get the x, y position of the markers.
  var chartLayout = chart.getChartLayoutInterface();

  for (var i = 0; i < annotations.length; i++) {
    var annotation = annotations[i];
    var row = getSelectRow(annotation.value);
    var x = chartLayout.getXLocation(data.getValue(row, Column.VALUE));
    var y = chartLayout.getYLocation(row);

    var annotationElement = document.createElement('div');
    annotationElement.className = 'chart-annotation';
    annotationElement.style.left = x + 'px';
    annotationElement.style.top = y + 'px';
    annotationElement.innerHTML = annotation.text;

    container.appendChild(annotationElement);
  }
}

/**
 * Set a marker to a different color.
 *
 * This is done in a very indirect way because the setSelection offered by the
 * google chart tools library is very subtle.
 *
 * Essentially, each data series has two data columns, for the unselected /
 * selected rows (See Column). These two columns are plotted as two data series
 * (and therefore two different colors) as a stacked column chart.
 *
 * Upon selection, the actual data value moves to the "select" column and the
 * value in the "value" column is set to be zero. This is reversed in the
 * clearSelection method.
 *
 * @param {string} target The selected data series element stored in the first
 *     column of the data table (i.e., the categorical column).
 */
function setSelection(target) {
  var value = target.innerText || target.textContent;
  var row = getSelectRow(value);
  data.setCell(row, Column.SELECT, data.getValue(row, Column.VALUE));
  data.setCell(row, Column.VALUE, 0);
  chart.draw(data, Options);
  chart.setSelection([{column: Column.SELECT, row: row}]);
  lastSelectedRow = row;
  logGraphicEvent('mouseover', value);
}

/**
 * See setSelection.
 */
function clearSelection(target) {
  var value = target.innerText || target.textContent;
  var row = getSelectRow(value);
  data.setCell(row, Column.VALUE, data.getValue(row, Column.SELECT));
  data.setCell(row, Column.SELECT, 0);
  chart.draw(data, Options);
  logGraphicEvent('mouseout', value);
}

/**
 * Gets the selected row based on the first column value.
 */
function getSelectRow(value) {
  return data.getFilteredRows([{column: 0, value: value}])[0];
}

